package com.robot.service.impl;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.robot.dao.entity.User;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.robot.common.enums.*;
import com.robot.common.exception.BusinessException;
import com.robot.common.utils.*;
import com.robot.dao.dto.CompanyInvitationDTO;
import com.robot.dao.dto.UserDTO;
import com.robot.dao.dto.UserLoginDTO;
import com.robot.dao.dto.UserUpdateDto;
import com.robot.dao.entity.*;
import com.robot.dao.mapper.*;
import com.robot.dao.vo.CompanyVO;
import com.robot.dao.vo.FileOverViewVO;
import com.robot.dao.vo.UserInfoVO;
import com.robot.service.UserService;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import static com.robot.common.enums.RoleCodeEnum.SUPER_MANAGER;


@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private IntegralMapper integralMapper;

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private IntegralLogMapper integralLogMapper;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private MinioClient minioClient;


    @Override
    public UserInfoVO geUserById(Integer id) {
        UserInfoVO userInfoVO = new UserInfoVO();
        User user = userMapper.selectById(id);
        if (ObjectUtils.isEmpty(user)) {
            return userInfoVO;
        }
        BeanUtils.copyProperties(user, userInfoVO);
        return userInfoVO;
    }


    @Override
    @Transactional
    public void setCompanyManager(UserDTO userDTO) {

        if (ObjectUtils.isEmpty(userDTO.getUserId())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未传入用户Id！");
        }
        User user = userMapper.selectById(userDTO.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未查询到用户信息！");
        }
        if (!userDTO.getCompanyCode().equals(user.getCompanyCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请检查该用户企业信息（不存在/已在其他企业中）！");
        }
        if (user.getRoleCode().equals(RoleCodeEnum.COMPANY_MANAGER.getCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户已存在在企业管理员身份！");
        }

        user.setRoleCode(RoleCodeEnum.COMPANY_MANAGER.getCode());
        userMapper.updateById(user);

    }

    @Override
    public String uploadUserImage(MultipartFile multipartFile) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        //TODO：待优化
        //不存在，创建bucket
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker =
                new SnowFlakeGenerateIdWorker(0L, 0L);
        String name = snowFlakeGenerateIdWorker.generateNextId();
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
        String bucketName = name;
        Map<Long, MultipartFile> multipartFiles = new HashMap<>();

        multipartFiles.put(101L, multipartFile);
        String fileUrl = "";
        Map<Long, String> upload = minioUtils.upload(bucketName, multipartFiles);
        for (Map.Entry<Long, String> entry : upload.entrySet()) {
            fileUrl = entry.getValue();

        }

        return fileUrl;

    }

    @Override
    public void addByInvitationCode(CompanyInvitationDTO companyInvitationDTO) {
        if (StringUtils.isBlank(companyInvitationDTO.getInvitationCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未传入企业邀请码！");
        }
        User user = userMapper.selectById(companyInvitationDTO.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未查询到用户信息！");
        }
        if (StringUtils.isNotBlank(user.getCompanyCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户已存在企业中！");

        }
        Company company = companyMapper.selectByInvitationCode(companyInvitationDTO.getInvitationCode());
        if (ObjectUtils.isEmpty(company)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未查询到公司信息，请传入有效邀请码！");
        }

        if (company.getCompanyType().equals(CompanyTypeEnum.TEAM.getCode())) {
            User userSearch = User.builder()
                    .companyCode(company.getCompanyCode())
                    .build();
            List<User> userList = userMapper.selectUserList(userSearch);
            if (ObjectUtils.isEmpty(userList)) {
                throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请核实企业信息，未查询到该企业存在相关用户！");
            }
            if (userList.size() >= 5) {
                throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "团队人数已满5人不可再加入！");
            }
        }

        user.setCompanyCode(company.getCompanyCode());
        user.setRoleCode(RoleCodeEnum.COMPANY_USER.getCode());
        userMapper.updateById(user);

    }


    @Override
    public void modifyUser(UserUpdateDto userUpdateDto) {
        if (StringUtils.isBlank(userUpdateDto.getUserId())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户ID为空！");
        }
        if (StringUtils.isBlank(userUpdateDto.getUserImageUrl())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "头像为空！");
        }
        if (StringUtils.isBlank(userUpdateDto.getUserName())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户名为空！");
        }
        User user = userMapper.selectById(userUpdateDto.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "未查询到用户信息！");
        }
        user.setUserName(userUpdateDto.getUserName());
        user.setUserHeadImgUrl(userUpdateDto.getUserImageUrl());
        userMapper.updateById(user);

    }


    @Override
    public void removeCompany(UserDTO userDTO) {
        User user = User.builder()
                .id(Long.valueOf(userDTO.getUserId()))
                .userPhone(userDTO.getUserPhone())
                .companyCode(userDTO.getCompanyCode())
                .build();
        User userInfo = userMapper.selectById(user);
        if (ObjectUtils.isEmpty(userInfo)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户不存在！");
        }
        if (StringUtils.isBlank(userInfo.getCompanyCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "用户已移除企业！");
        }
        if (userInfo.getRoleCode().equals(RoleCodeEnum.COMPANY_MANAGER.getCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "企业管理员不支持移除企业！");
        }
        //将用户角色、企业编码更改
        userInfo.setRoleCode(RoleCodeEnum.NORMAL_USER.getCode());
        userInfo.setCompanyCode("");
        userMapper.updateById(userInfo);

    }

    @Override
    public UserInfoVO register(UserLoginDTO userLoginDTO) throws Exception {
        this.verifyPhoneAndPassWord(userLoginDTO);

        //去内存缓存中查找验证码是否存在
        String code = CaptchaCacheWithGuava.getCaptcha(userLoginDTO.getUserPhone());
        if (StringUtils.isBlank(code)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "验证码已过期请重新发送！");
        }
        if (!code.equals(userLoginDTO.getCode())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "验证码错误！");
        }

        //TODO:加密算法更改
        //手机号验证是否注册过
        String phoneSecret = AESEncryptionUtils.encrypt(userLoginDTO.getUserPhone(), AESEncryptionUtils.generateKeyTemporary());
        UserInfoVO user = userMapper.searchByPhone(phoneSecret);
        if (!ObjectUtils.isEmpty(user)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "手机号已被注册！");
        }
        UserInfoVO userInfoVO = this.buildIntegralAndUser(userLoginDTO, phoneSecret);
        return userInfoVO;

    }

    @Override
    public UserInfoVO logOn(UserLoginDTO userLoginDTO) throws Exception {
        this.verifyPhoneAndPassWord(userLoginDTO);

        //手机号验证是否注册过
        String phoneSecret = AESEncryptionUtils.encrypt(userLoginDTO.getUserPhone(), AESEncryptionUtils.generateKeyTemporary());
        UserInfoVO user = userMapper.searchByPhone(phoneSecret);
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请先注册后再登录！");
        }

        //验证账号密码
        userLoginDTO.setUserPhone(phoneSecret);

        UserInfoVO userInfoVO = userMapper.searchByPhoneAndPassWord(userLoginDTO);
        if (ObjectUtils.isEmpty(userInfoVO)) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "账号密码错误！");
        }

        //根据userId生成token
        String token = jwtTokenUtil.generateToken(userInfoVO.getId().toString());
        if (userInfoVO.getIsFirstLogin().equals(IsValidEnum.NO.getCode())) {
            User userRes = userMapper.selectById(userInfoVO.getId());
            userRes.setIsFirstLogin(IsDeleteEnum.EXIST.getValue());
            userMapper.updateById(userRes);
        }

        log.info("token.......{}", token);
        userInfoVO.setToken(token);
        userInfoVO.setIsFirstLogin(IsDeleteEnum.EXIST.getValue());


        return userInfoVO;

    }

    @Override
    public Boolean analyzeKey(String key) throws Exception {
        try {
            String currentDateFront = AESEncryptionUtils.decrypt(key, AESEncryptionUtils.generateKeyTemporary());
            log.info("解密后：{}", currentDateFront);
            String currentDateEnd = DateUtil.now().toString();

            // 设置日期格式
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

            // 将字符串转换为Date对象
            Date date1 = dateFormat.parse(currentDateFront);
            Date date2 = dateFormat.parse(currentDateEnd);
            // 计算两个日期之间的差异，单位为毫秒
            long difference = date2.getTime() - date1.getTime();
            long diffSeconds = (difference / 1000) % 60;
            if (diffSeconds > 30) {
                return Boolean.TRUE;
            }
        } catch (Exception e) {
            return Boolean.FALSE;
        }

        return Boolean.FALSE;
    }

    @Transactional
    public UserInfoVO buildIntegralAndUser(UserLoginDTO userLoginDTO, String phoneSecret) {


        //创建积分账户(个人账户积分有效期2周)
        Integral integral = Integral.builder()
                .integralScore(IntegralScoreEnum.NORMAL_USER.getCode())
                .startTime(DateTime.now())
                .endTime(DateFullUtils.addDate(DateTime.now(), 14))
                .build();
        integralMapper.insert(integral);

        //存储注册用户
        User userNew = User.builder()
                .userPhone(phoneSecret)
                .userName(PhoneEncryptUtils.encryptPhoneNumber(userLoginDTO.getUserPhone()))
                .userPassword(userLoginDTO.getUserPassWord())
                .userHeadImgUrl("")
                .isFirstLogin(IsValidEnum.NO.getCode())
                .IntegralId(integral.getId())
                .roleCode(RoleCodeEnum.NORMAL_USER.getCode())
                .build();
        userMapper.insert(userNew);


        //积分操作日志
        //TODO:抽出优化
        IntegralLog integralLog = IntegralLog.builder()
                .integralScore(integral.getIntegralScore())
                .type(IntegralTypeEnum.ADD.getCode())
                .userId(userNew.getId())
                .remark("个人新建积分账户")
                .build();
        integralLogMapper.insert(integralLog);

        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(userNew, userInfoVO);
        BeanUtils.copyProperties(integral, userInfoVO);

        //根据userId生成token
        String token = jwtTokenUtil.generateToken(userInfoVO.getId().toString());
        log.info("token.......{}", token);
        userInfoVO.setToken(token);
        return userInfoVO;

    }

    /**
     * 验证手机号密码格式
     *
     * @param userLoginDTO
     */
    private void verifyPhoneAndPassWord(UserLoginDTO userLoginDTO) {
        //验证手机号格式
        Boolean isQualified = PhoneNumberValidator.isValidPhoneNumber(userLoginDTO.getUserPhone());
        if (!isQualified) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请传入正确的手机号！");
        }

        if (StringUtils.isBlank(userLoginDTO.getUserPassWord())) {
            throw new BusinessException(ResponseEnum.ILLEGAL_PARAMETER.getCode(), "请输入密码！");
        }
    }

    public List<Long> getManagerUserIDList(){
        QueryWrapper<User> queryWrapper = Wrappers.query();
        queryWrapper.eq("role_code", SUPER_MANAGER.getCode()).last("limit 10");//超级管理员不会超过10个
        List<User> userList = this.list(queryWrapper);
        List<Long> ids = new ArrayList<>();
        for (User user : userList) {
            ids.add(user.getId());
        }
        return ids;
    }


}
